﻿#include"Image2Mesh.hpp"
#include"../../TesMath/TesLinespace.h"

namespace MMF { namespace Mesh {


Image2Mesh::Image2Mesh(ImageInterface& img, int lerpNum)
    : mImg(img)
    , mLerpNum(lerpNum)
{

}


void Image2Mesh::Convert()
{
    int imgW = mImg.Width();
    int imgH = mImg.Height();
    int w = ((imgW - 1) * (1 + mLerpNum) + 1);
    int h = ((imgH - 1) * (1 + mLerpNum) + 1);

    mMesh.vertices.resize(w * h);
    mMesh.vertices.clear();
    mMesh.colors.resize(w * h);
    mMesh.colors.clear();
    mMesh.normals.resize(w * h);
    mMesh.normals.clear();
    mMesh.uv.resize(w * h);
    mMesh.uv.clear();

    float delta = 1.0f / (mLerpNum + 1);    //线段的数量比点少一个

    //创建变量
    float lerpValue;
    TesVector3 lerpColor;
    TesVector3 pt;

    for (int y = 0; y < h; y++)
    {
        for (int x = 0; x < w; x++)
        {
            //获取栅格图像的点
            int imgX = x / (mLerpNum + 2);
            int imgY = y / (mLerpNum + 2);
            float lerpX = x % (mLerpNum + 2) * 1.0f;
            float lerpY = y % (mLerpNum + 2) * 1.0f;

            //由于要使用到后面一个点必须限制
            if (x < w - 1 && y < h - 1)
            {
                //创建线性插值空间
                TesLinespace<float> col0 = TesLinespace<float>(mImg.GetValue(imgX, imgY), mImg.GetValue(imgX + 1, imgY), 1.0f);
                TesLinespace<float> col1 = TesLinespace<float>(mImg.GetValue(imgX, imgY + 1), mImg.GetValue(imgX + 1, imgY + 1), 1.0f);
                TesLinespace<TesVector3> color0 = TesLinespace<TesVector3>(mImg.GetColor(imgX, imgY), mImg.GetColor(imgX + 1, imgY), 1.0f);
                TesLinespace<TesVector3> color1 = TesLinespace<TesVector3>(mImg.GetColor(imgX, imgY + 1), mImg.GetColor(imgX + 1, imgY + 1), 1.0f);

                //计算线性插值
                float lerpValueX0 = col0.GetValue((double)lerpX * delta);
                float lerpValueX1 = col1.GetValue((double)lerpX * delta);
                TesVector3 lerpColorX0 = color0.GetValue(lerpX * delta);
                TesVector3 lerpColorX1 = color1.GetValue(lerpX * delta);

                //纵向线性插值空间
                TesLinespace<float> row = TesLinespace<float>(lerpValueX0, lerpValueX1, 1.0f);
                TesLinespace<TesVector3> rowColor = TesLinespace<TesVector3>(lerpColorX0, lerpColorX1, 1.0f);
                lerpValue = row.GetValue(lerpY * delta);
                lerpColor = rowColor.GetValue(lerpY * delta);
            }
            else if (x < w - 1 && y == h - 1)
            {
                //最后一列没有下一列，直接纵插值
                TesLinespace<float> col = TesLinespace<float>(mImg.GetValue(imgX, imgY), mImg.GetValue(imgX + 1, imgY), 1.0f);
                TesLinespace<TesVector3> colColor = TesLinespace<TesVector3>(mImg.GetColor(imgX, imgY), mImg.GetColor(imgX + 1, imgY), 1.0f);
                lerpValue = col.GetValue(lerpX * delta);
                lerpColor = colColor.GetValue(lerpX * delta);
            }
            else if (x == w - 1 && y < h - 1)
            {
                //最后一排没有下一排了直接横向插值
                TesLinespace<float> row = TesLinespace<float>(mImg.GetValue(mImg.Width() - 1, imgY), mImg.GetValue(mImg.Width() - 1, imgY + 1), 1.0f);
                TesLinespace<TesVector3> rowColor = TesLinespace<TesVector3>(mImg.GetColor(mImg.Width() - 1, imgY), mImg.GetColor(mImg.Width() - 1, imgY + 1), 1.0f);
                lerpValue = row.GetValue(lerpY * delta);
                lerpColor = rowColor.GetValue(lerpY * delta);
            }
            else 
            {
                //这里仅仅最后一个点
                lerpValue = mImg.GetValue(mImg.Width() - 1, mImg.Height() - 1);
                lerpColor = mImg.GetColor(mImg.Width() - 1, mImg.Height() - 1);
            }

            //组装三维点:x, y , z
            //将图片的y转换为三维图的z值，使不需要再3为场景中进行旋转
            pt = TesVector3(x * delta, lerpValue, y * delta); //y值为图像的能量强度
            pt.x -= (imgW / 2.0f);  //x移到图片中间
            pt.z -= (imgH / 2.0f);  //z移到图片中间
            mMesh.vertices.push_back(pt);

            //组装点的颜色
            mMesh.colors.push_back(lerpColor);

            //组装法线，值z = -1.0(右手坐标系, 如果是左手需要反过来)
            TesVector3 normal = TesVector3(0.0f, 1.0f, 0.0f);
            mMesh.normals.push_back(normal);

            //组装纹理坐标
            TesVector2 uv = TesVector2(x / (w * 1.0f), 1.0f - y / (h * 1.0f));
            mMesh.uv.push_back(uv);

            //生成三角形
            //四个点能生成两个三角形
            if (y > 0 && x < w - 1)
            {
                //生成三角形1
                int p0 = x + (y - 1) * w; //x + y * w;            
                int p1 = x + y * w; //x + (y - 1) * w;       
                int p2 = (x + 1) + y * w; //(x + 1) + y * w;      

                //生成三角形2
                int p10 = x + (y - 1) * w; //x + (y - 1) * w;      
                int p11 = (x + 1) + y * w; //(x + 1) + (y - 1) * w;
                int p12 = (x + 1) + (y - 1) * w; //(x + 1) + y * w;      

                //入队顶点索引值
                mMesh.triangles.push_back(p0);
                mMesh.triangles.push_back(p1);
                mMesh.triangles.push_back(p2);
                mMesh.triangles.push_back(p10);
                mMesh.triangles.push_back(p11);
                mMesh.triangles.push_back(p12);
            }
        }
    }
}


const TesMesh& Image2Mesh::Mesh()
{
    return mMesh;
}



}}